/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       artifact_set.cpp

	$Header:  $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "artifact_set.h"

#include "handler.h"
#include "owned_ptr.h"
#include "sized_int_types.h"
#include "streambuf_operators.h"

namespace
{
	int const k_version = 0;
}

// ------------------------------------------------------------
// ------------------------------------------------------------
bool t_artifact_set::read( std::streambuf & stream, bool new_artifact_default )
{
	int index;
	if ( !read_impl( stream, index ) )
		return false;

	// Handle new artifacts
	for ( ; index < size(); ++index )
		set( index, new_artifact_default );

	return true;
}

// ------------------------------------------------------------
// read artifact set
// Handles case where new artifacts have been added since the 
// bitset was written out
// ------------------------------------------------------------
bool t_artifact_set::read( std::streambuf& stream, t_handler_2< t_artifact_type, bool & > new_artifact_handler )
{
	int index;
	if ( !read_impl( stream, index ) )
		return false;

	// Handle new artifacts
	for ( ; index < size(); index++ )
	{
		bool setting;
		new_artifact_handler( t_artifact_type( index ), setting );
		set( index, setting );
	}

	return true;
}

// ------------------------------------------------------------
// write artifact set
// ------------------------------------------------------------
bool t_artifact_set::write( std::streambuf& stream ) const
{
	put< t_uint16 >( stream, k_version );
	put< t_uint16 >( stream, size() );

	t_uint16 bytes = ( size() + 7 ) / 8;

	t_owned_array< unsigned char > buffer( new unsigned char [ bytes ] );
	memset( buffer.get(), 0, bytes );

	int index;
	for ( index = 0; index < size(); index++ )
	{
		if ( test( index ) )
			buffer[ index / 8 ] |= ( 1 << ( index % 8 ) );
	}

	return ::write( stream, buffer.get(), bytes ) == bytes;
}

// ------------------------------------------------------------
// ------------------------------------------------------------
bool t_artifact_set::read_impl( std::streambuf & stream, int & original_size_arg )
{
	t_uint16 version = get< t_uint16 >( stream );
	t_uint16 original_size = get< t_uint16 >( stream );

	if ( original_size > size() )
		return false;

	t_uint16 bytes = ( original_size + 7 ) / 8;

	t_owned_array< unsigned char > buffer( new unsigned char [ bytes ] );
	if ( ::read( stream, buffer.get(), bytes ) != bytes )
		return false;

	int index;
	for ( index = 0; index < original_size; index++ )
		set( index, ( buffer[ index / 8 ] >> ( index % 8 ) ) & 0x1 );

	original_size_arg = original_size;

	return true;
}
